module;
#include <QObject>
#include <QJsonObject>
#include <QJsonDocument>
#include <QFile>
#include <QIODevice>
#include <QModbusRtuSerialClient>
#include <QModbusTcpClient>
#include <QSerialPort>
#include <QDebug>
export module XYmodbus;

export class ModbusClientHandle : public QObject
{
    Q_OBJECT

public:
    explicit ModbusClientHandle(QObject *parent = nullptr);
    ~ModbusClientHandle();

   Q_INVOKABLE bool loadConfig(const QString &configFilePath);//加载配置文件，connection数据给connectionCfg,register数据给registersCfg
    //配置文件有连接类型：TCP/RTU IP地址 端口号 站号 超时时间 连接次数 RTU连接还有波特率 校验位等modbus连接需要的参数 还有标签名，寄存器类型、地址，站号
   Q_INVOKABLE bool connectToDevice();//通过connectionCfg设置连接参数,发送modbus设备连接请求
   Q_INVOKABLE bool disconnectToDevice();//断开连接modbus设备
   Q_INVOKABLE void readModbusValues();//通过配置变量connectionCfg读取modbus设备数据
   Q_INVOKABLE void writeModbusValues(const QMap<QString, QVariant> &wDataMap);//通过配置变量connectionCfg写入wDataMap数据到modbus设备

signals:
    void ModbusStateChanged(int state, QString errorMassage);//modbus设备连接状态变更信号,如果有错误信息则发出错误信息
    void readCompleted(const QString &registerName, const QVariant &registerValue);//读完单个寄存器并且数值有变化时发的信号
    void readCompletedChanged(const QString &registerName, const QVariant &registerValue);//读完单个寄存器发信号的信号
    void allReadCompleted(const QMap<QString, QVariant> &dataMap);//所有数据读取完成信号，返回dataMap
    void writeCompleted(bool success, const QString &registerName, const QString &error = QString());//写完单个寄存器发信号的信号
    void allWritesCompleted();//所有wDataMap数据写入完成发送的信号
public slots:
    void loadConfigSlot(const QString &configFilePath);//普通方法的槽形式，方便跨线程使用
    void connectToDeviceSlot();//普通方法的槽形式，方便跨线程使用
    void disconnectToDeviceSlot();//普通方法的槽形式，方便跨线程使用
    void readModbusValuesSlot();//普通方法的槽形式，方便跨线程使用
    void writeModbusValuesSlot(const QMap<QString, QVariant> &wDataMap);//普通方法的槽形式，方便跨线程使用

private slots:
    void onReadReply(QModbusReply *reply, const QString &registerName);//readModbusValues()后，跟踪读取状态，读取完成后发送读完信号
    void onWriteReply(QModbusReply *reply, const QString &registerName);//writeModbusValue()后，跟踪写入状态，写完后发送写完信号

private:
    QModbusDataUnit::RegisterType getRegisterType(const QString &type);//根据配置文件获取寄存器类型
    QSerialPort::Parity stringToParity(const QString &parityStr);

    QModbusClient *modbusDevice;//modbus设备
    QJsonObject config;//JSON配置文件
    QMap<QString, QVariant> connectionCfg;//modbus连接配置文件
    QMap<QString, QMap<QString, QVariant>> registersCfg;//寄存器配置文件
    QMap<QString, QVariant> dataMap;//读取modbus设备数据时保存在这里
    QMap<QString, QVariant> dataMapOld;//用于比较读取的数据与原来的数据/刚建立连接时清除数据
    bool firstRead;//
    int pendingReadRequests;//读取请求队列
    int pendingWriteRequests;//写入请求队列
};

/*
Json文件示例
{
    "Connection": {
        "Type": "RTU",
        "IP": "COM3",
        "BaudRate": 9600,
        "Parity": "EvenParity",
        "DataBits": 8,
        "StopBits": 1,
        "UnitID": 1,
        "Timeout": 500,
        "Retries": 3
    },
    "Registers": [
        {
            "Name": "Status",
            "Type": "Coil",
            "Address": 100,
            "UnitID": 1
        },
        {
            "Name": "Temperature",
            "Type": "InputRegister",
            "Address": 200,
            "UnitID": 1
        }
    ]
}


{
    "Connection": {
        "Type": "TCP",
        "IP": "192.168.1.100",
        "Port": 502,
        "UnitID": 1,
        "Timeout": 500,
        "Retries": 3
    },
    "Registers": [
        {
            "Name": "MotorSpeed",
            "Type": "HoldingRegister",
            "Address": 1000,
            "UnitID": 1
        },
        {
            "Name": "Pressure",
            "Type": "InputRegister",
            "Address": 300,
            "UnitID": 1
        }
    ]
}

*/
